/*
 * RTSAI - Real-Time Strategy engine for AI research
 * Copyright(C) 2006 DIMAp-UFRN, licensed under LGPL
 *
 * Simple C++ log library
 * Lib initially based on .h by August Schwerdfeger
 * (http://www.tc.umn.edu/~schw0709/programs/log_libraries.html)
 *
 * Example of usage:
 *    Logger::set_level ( Logger::DEBUG );
 *    LOG << "This message will always appear" << std::endl;
 *    LOG_DEBUG << "The value of x is " << x << std:endl;
 */

#ifndef __LOGGER_H
#define __LOGGER_H

#include <iostream>

/*! Constants for the different importance levels of the log messages */
/// Constant to LOG_DEBUG
#define LOG_DEBUG   (Logger::get_logger(Logger::DEBUG))
/// Constant to LOG_WARNING
#define LOG_WARNING (Logger::get_logger(Logger::WARNING))
/// Constant to LOG_FAIL
#define LOG_FAIL    (Logger::get_logger(Logger::FAIL))
/// Constant LOG
#define LOG         (Logger::get_logger(Logger::ALLWAYS))

//! Class Logger
/*! This class implements a logger that help us to debug the code
 */
class Logger
{

    public:
        /// Constants that defines a Log Level (e.g., debug, warning...)
        enum LogLevel
        {
            DEBUG,
            WARNING,
            FAIL,
            ALLWAYS,
            NONE
        };

        static Logger& get_logger ( LogLevel newLevel );

        // Functions to get and set the log level
        static LogLevel get_level();
        static void set_level ( LogLevel newLevel );

        // Logs to a specified stream, log level specified
        static void set_output ( std::ostream& newLogDev );

        // Operator to pass the message to the stream
        template <class T> std::ostream& operator<<(T x);

    private:
        // singleton pattern
        // static Logger logger;
        Logger();
        static Logger& logger();
     
        /// Stream to which to send messages
        std::ostream  *stream;
        /// Current log level
        LogLevel  logLevel;
        /// Level of message (as set by operator)
        LogLevel  msgLevel;
};


/*! Overloaded operator <<
 */
template <class T>
std::ostream& Logger :: operator<<(T x)
{
    if ( msgLevel >= logLevel )
        (*stream) << x;
    return (*stream);
}

#endif // #ifndef __LOGGER_H
